<template>
    <div class="person">
        <h1> watch 的第一种情况：监视 ref 修饰的基础类型 </h1>
        <h4> sum:{{ sum }}</h4>
        <button @click="sumAdd">点击 sum + 1</button>

        <h1> watch 的第二种情况：监视 ref 修饰的对象类型 </h1>
        <h2>姓名：{{ person.name }}</h2>
        <h2>年龄：{{ person.age }}</h2>
        <h2>性别：{{ person.gender }}</h2>
        <button @click="changeName">修改名称</button>
        <button @click="changeAge">修改年龄</button>
        <button @click="changeObj">修改对象</button>

        <h1> watch 的第三种情况：监视 reactive 修饰的对象类型 </h1>
        <h2>姓名：{{ person2.name }}</h2>
        <h2>年龄：{{ person2.age }}</h2>
        <h2>性别：{{ person2.gender }}</h2>
        <button @click="changeName2">修改名称</button>
        <button @click="changeAge2">修改年龄</button>
        <button @click="changeObj2">修改对象</button>

        <h1> watch 的第四种情况：监视【ref】或【reactive】定义的【对象类型】数据中的某个属性 </h1>
        
        <h2>姓名：{{ person3.name }}</h2>
        <h2>年龄：{{ person3.age }}</h2>
        <h2>汽车：{{ person3.car.c1}}，{{ person3.car.c2 }}</h2>
        <button @click="changeName3">修改名称</button>
        <button @click="changeAge3">修改年龄</button>
        <button @click="changeCar1">修改第一台车</button>
        <button @click="changeCar2">修改第二台车</button>
        <button @click="changeCar">修改Car对象</button>

        <h1> watch 的第【五种】情况：监视【多个属性】</h1>
        
        <h2>姓名：{{ person4.name }}</h2>
        <h2>年龄：{{ person4.age }}</h2>
        <h2>汽车：{{ person4.car.c1}}，{{ person4.car.c2 }}</h2>
        <button @click="changeName4">修改名称</button>
        <button @click="changeAge4">修改年龄</button>
        <button @click="changeCar3">修改第一台车</button>
        <button @click="changeCar4">修改第二台车</button>
        <button @click="changeCar5">修改Car对象</button>
    </div>
</template>

<script lang="ts" setup name="person">

import { reactive, ref, watch } from 'vue'

let sum = ref(0)

function sumAdd() {
    sum.value += 1;
}

//监视的情况一：监视{ref}定义的【基本类型】数据
let stopWatch = watch(sum, (o, n) => {
    console.log('sum 变化了 ', o, n)
    if (n >= 10) {
        //这是啥，不管了嘛？
        //经过测试还真是 ，如果stopwatch ，那么则不会监视这个属性了
        stopWatch();
    }
})

//监视的情况二  监视的是 ref 修饰的对象
let person = ref({
    name: "xiaoming",
    age: 19,
    gender: '男'
})

// ref 修饰的对象 如果是改变的对象的属性，则 新旧对象都是同一个对象
// ref 修饰的对象 如果是改变的对象，则旧对象是原本的对象
// 若想监视对象内部属性的变化，需要手动开启深度监视 {"deep":true}
let personWatch = watch(person, (newValue, oldValue) => {
    console.log('监视ref修饰的person对象', oldValue, newValue)
}, { "deep": true })

function changeName() {
    person.value.name += '~';
}

function changeAge() {
    person.value.age += 1
}


function changeObj() {
    person.value = {
        name: "小蓝蓝",
        age: 23,
        gender: '女'
    }
}

let person2 = reactive({
    name: "小蓝蓝",
    age: 23,
    gender: '女'
})

function changeName2() {
    person2.name += '~';
}

function changeAge2() {
    person2.age += 1
}

function changeObj2() {

    //如果需要改变响应式的对象，如果是使用的reactive 修饰的，需要使用 Object.assign 来修改
    Object.assign(person2,{
        name: "小蓝蓝Plus",
        age: 25,
        gender: '女'
    })
}

// 如果是使用的 reactive 修饰的对象，默认开始了 deep 深度监视
const watchPerson2 = watch(person2, (newValue, oldValue) => {
    console.log("有人修改了 person2 ")
    console.log(oldValue, newValue)
})



//第四种情况，监视 ref 或者 reactive 定义的对象类型 数据中的某个属性

let person3 = reactive({
    name : "王总",
    age  : 19,
    car : {
        c1:"BMW",
        c2:"奔驰"
    } 
})

function changeName3() {
    person3.name += '~';
}

function changeAge3() {
    person3.age += 1
}

function changeCar1(){
    person3.car.c1 = "雷克萨斯"
}

function changeCar2(){
    person3.car.c2 = "奥拓"
}

function changeCar(){

    // Object.assign(person3.car,{
    //     c1:"雅迪",
    //     c2:"玫瑰之约"
    // })

    person3.car = {
        c1:"雅迪",
        c2:"玫瑰之约"
    }
}

//监视对象中的属性，如果是基本类型

/**
 * 这样只能监视到对象类型的变化，但是无法
watch(person3,(o,n)=>{
    console.log(o,n)
},{deep:true})

**/
//例如，监视 person3 的名称
// 注意点：监视，情况四：监视响应式对象中的某个属性，且该属性是基本类型的，要写成函数式
watch(()=> person3.name,(newValue,oldValue)=>{
    console.log('person3 的 name 变化了 ',oldValue,newValue)
})

//注意点：监视 响应式对象中的某个属性，如果该属性是对象类型，则可以直接写，也可以写函数式
//如果是直接改变 car 对象，那么则无法监视到 car 的变化
watch(person3.car,(newValue,oldValue)=>{
    console.log('person3 的 car 属性有变化噢，现在是【对象式】的写法 ',newValue,oldValue)
},{deep:true})

//更推荐这种写法
watch(() => person3.car,(newValue,oldValue)=>{
    console.log('person3 的 car 现在是【 函数式 】的写法 ',newValue,oldValue)
},{deep:true})


//第5中情况，监视多个属性
let person4 = reactive({
    name : "王总",
    age  : 42,
    car : {
        c1:"BMW",
        c2:"奔驰"
    } 
})

function changeName4() {
    person4.name += '~';
}

function changeAge4() {
    person4.age += 1
}

function changeCar3(){
    person4.car.c1 = "雷克萨斯"
}

function changeCar4(){
    person4.car.c2 = "奥拓"
}

function changeCar5(){

    // person4.car = {
    //     c1:"雅迪",
    //     c2:"玫瑰之约"
    // }

    Object.assign(person4.car ,{
        c1:"雅迪",
        c2:"玫瑰之约"
    })
}

/**
 * 同时监视多个属性,这好像监视属性的话 只监视到了第一个啊
 * */
 watch([()=>person4.age,person4.name,person4.car],(newValue,oldValue)=>{
    console.log('person 多个属性变化了',oldValue,newValue)
  },{deep:true})


</script>

<style>
.person {
    width: 100%;
    background-color: rgb(108, 15, 239);
    border-radius: 2%;
}
button{
    border: 1px burlywood ;
    border-radius: 3%;
    margin-left: 10px;
    background-color: chocolate;
}
</style>